<script lang="ts" setup>
import { PropType, watch, ref, shallowRef, onBeforeUnmount, nextTick, computed } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { i18nChangeLanguage, IDomEditor, IEditorConfig } from '@wangeditor/editor'
import { propTypes } from '@/utils/propTypes'
import { isNumber } from '@/utils/is'
import { ElMessage, ElImage, ElImageViewer } from 'element-plus'
import { useLocaleStore } from '@/store/modules/locale'
import { getAccessToken } from '@/utils/auth'
import { getUploadUrl } from '@/components/UploadFile/src/useUpload'

defineOptions({ name: 'Editor' })

type InsertFnType = (url: string, alt: string, href: string) => void

const localeStore = useLocaleStore()

const currentLocale = computed(() => localeStore.getCurrentLocale)

i18nChangeLanguage(unref(currentLocale).lang)

const props = defineProps({
  editorId: propTypes.string.def('wangeEditor-1'),
  height: propTypes.oneOfType([Number, String]).def('500px'),
  editorConfig: {
    type: Object as PropType<Partial<IEditorConfig>>,
    default: () => undefined
  },
  readonly: propTypes.bool.def(false),
  modelValue: propTypes.string.def('')
})

const emit = defineEmits(['change', 'update:modelValue'])

// 编辑器实例，必须用 shallowRef
const editorRef = shallowRef<IDomEditor>()

// 图片预览相关状态
const previewVisible = ref(false)
const previewImage = ref('')
const previewImages = ref<string[]>([])

const valueHtml = ref('')

watch(
    () => props.modelValue,
    (val: string) => {
      if (!val) {
        val = ''
      }
      if (val === unref(valueHtml)) return
      valueHtml.value = val
    },
    {
      immediate: true
    }
)

// 监听HTML变化
watch(
    () => valueHtml.value,
    (val: string) => {
      emit('update:modelValue', val)
    }
)

// 处理编辑器创建完成
const handleCreated = (editor: IDomEditor) => {
  editorRef.value = editor
  // 初始化图片双击事件监听
  setupImageDoubleClickHandler(editor)
}

// 设置图片双击事件处理
const setupImageDoubleClickHandler = (editor: IDomEditor) => {
  if (!editor) return

  // 获取编辑器内容区域
  const contentContainer = editor.getEditableContainer()
  if (!contentContainer) return

  // 创建MutationObserver监听内容变化，确保新添加的图片也能被处理
  const observer = new MutationObserver(mutations => {
    mutations.forEach(mutation => {
      // 为所有图片添加双击事件
      const images = contentContainer.querySelectorAll('img')
      images.forEach(img => {
        // 移除已存在的事件监听，避免重复绑定
        img.ondblclick = null

        // 添加双击事件
        img.ondblclick = (e) => {
          e.stopPropagation()
          const imgUrl = img.src
          if (imgUrl) {
            // 准备预览图片数据
            previewImage.value = imgUrl
            previewImages.value = [imgUrl]
            // 显示预览
            previewVisible.value = true
          }
        }
      })
    })
  })

  // 开始观察编辑器内容变化
  observer.observe(contentContainer, {
    childList: true,
    subtree: true,
    attributes: true
  })

  // 组件销毁时停止观察
  onBeforeUnmount(() => {
    observer.disconnect()
  })
}

// 关闭图片预览
const handleClosePreview = () => {
  previewVisible.value = false
  previewImage.value = ''
  previewImages.value = []
}

// 编辑器配置
const editorConfig = computed((): IEditorConfig => {
  return Object.assign(
      {
        placeholder: '请输入内容...',
        readOnly: props.readonly,
        customAlert: (s: string, t: string) => {
          switch (t) {
            case 'success':
              ElMessage.success(s)
              break
            case 'info':
              ElMessage.info(s)
              break
            case 'warning':
              ElMessage.warning(s)
              break
            case 'error':
              ElMessage.error(s)
              break
            default:
              ElMessage.info(s)
              break
          }
        },
        autoFocus: false,
        scroll: true,
        MENU_CONF: {
          ['uploadImage']: {
            server: getUploadUrl(),
            // 单个文件的最大体积限制，默认为 2M
            maxFileSize: 5 * 1024 * 1024,
            // 最多可上传几个文件，默认为 100
            maxNumberOfFiles: 10,
            // 选择文件时的类型限制，默认为 ['image/*'] 。如不想限制，则设置为 []
            allowedFileTypes: ['image/*'],

            // 自定义增加 http header
            headers: {
              Accept: '*',
              Authorization: 'Bearer ' + getAccessToken(),
            },

            // 超时时间，默认为 10 秒
            timeout: 15 * 1000, // 15 秒

            // form-data fieldName，后端接口参数名称
            fieldName: 'file',

            // 上传之前触发
            onBeforeUpload(file: File) {
              return file
            },
            // 上传进度的回调函数
            onProgress(progress: number) {
              console.log('progress', progress)
            },
            onSuccess(file: File, res: any) {
              console.log('onSuccess', file, res)
            },
            onFailed(file: File, res: any) {
              alert(res.message)
              console.log('onFailed', file, res)
            },
            onError(file: File, err: any, res: any) {
              alert(err.message)
              console.error('onError', file, err, res)
            },
            // 自定义插入图片
            customInsert(res: any, insertFn: InsertFnType) {
              insertFn(res.data, 'image', res.data)
            }
          },
          ['uploadVideo']: {
            server: getUploadUrl(),
            // 单个文件的最大体积限制，默认为 10M
            maxFileSize: 10 * 1024 * 1024,
            // 最多可上传几个文件，默认为 100
            maxNumberOfFiles: 10,
            // 选择文件时的类型限制，默认为 ['video/*'] 。如不想限制，则设置为 []
            allowedFileTypes: ['video/*'],

            // 自定义增加 http header
            headers: {
              Accept: '*',
              Authorization: 'Bearer ' + getAccessToken(),
            },

            // 超时时间，默认为 30 秒
            timeout: 15 * 1000, // 15 秒

            // form-data fieldName，后端接口参数名称
            fieldName: 'file',

            // 上传之前触发
            onBeforeUpload(file: File) {
              return file
            },
            // 上传进度的回调函数
            onProgress(progress: number) {
              console.log('progress', progress)
            },
            onSuccess(file: File, res: any) {
              console.log('onSuccess', file, res)
            },
            onFailed(file: File, res: any) {
              alert(res.message)
              console.log('onFailed', file, res)
            },
            onError(file: File, err: any, res: any) {
              alert(err.message)
              console.error('onError', file, err, res)
            },
            // 自定义插入视频
            customInsert(res: any, insertFn: InsertFnType) {
              insertFn(res.data, 'mp4', res.data)
            }
          }
        },
        uploadImgShowBase64: true
      },
      props.editorConfig || {}
  )
})

const editorStyle = computed(() => {
  return {
    height: isNumber(props.height) ? `${props.height}px` : props.height
  }
})

// 内容变化回调函数
const handleChange = (editor: IDomEditor) => {
  emit('change', editor)
}

// 组件销毁时，及时销毁编辑器
onBeforeUnmount(() => {
  const editor = unref(editorRef.value)
  editor?.destroy()
})

const getEditorRef = async (): Promise<IDomEditor> => {
  await nextTick()
  return unref(editorRef.value) as IDomEditor
}

defineExpose({
  getEditorRef
})
</script>

<template>
  <div class="border-1 border-solid border-[var(--tags-view-border-color)] z-10">
    <!-- 工具栏 -->
    <Toolbar
        :editor="editorRef"
        :editorId="editorId"
        class="border-0 b-b-1 border-solid border-[var(--tags-view-border-color)]"
    />
    <!-- 编辑器 -->
    <Editor
        v-model="valueHtml"
        :defaultConfig="editorConfig"
        :editorId="editorId"
        :style="editorStyle"
        @on-change="handleChange"
        @on-created="handleCreated"
    />

    <!-- 图片预览组件 -->
    <el-image-viewer
        v-if="previewVisible"
        :url-list="previewImages"
        :initial-index="0"
        @close="handleClosePreview"
        :z-index="999999999"
    />
  </div>
</template>

<style src="@wangeditor/editor/dist/css/style.css"></style>
